<template>
  <el-card shadow="never" class="rd-8 mb-8">
    <el-input v-model="filterText" placeholder="请输入关键字进行过滤" />
  </el-card>
  <el-card shadow="never" class="rd-8">
    <template #header>
      <div class="flex flex-justify-between">
        <div>
          <el-button
            icon="Plus"
            type="primary"
            plain
            v-if="draggable"
            :disabled="updateNodes.length == 0"
            @click="batchSave"
          >
            批量保存
          </el-button>
          <el-button
            icon="Delete"
            type="danger"
            plain
            @click="batchDelete"
            :disabled="tids.length == 0"
          >
            批量删除
          </el-button>
        </div>
        <el-switch
          v-model="draggable"
          active-text="开启拖拽"
          inactive-text="关闭拖拽"
        ></el-switch>
      </div>
    </template>
    <el-tree
      ref="treeRef"
      :allow-drop="allowDrop"
      :data="data"
      node-key="cid"
      :draggable="draggable"
      :expand-on-click-node="false"
      :default-expanded-keys="expandedKey"
      show-checkbox
      :props="defaultProps"
      @check="handleCheck"
      @node-drop="handleDrop"
      :filter-node-method="filterNode"
    >
      <template #default="{ node, data }">
        <span class="custom-tree-node">
          <span>{{ node.label }}</span>
          <span>
            <el-button
              type="primary"
              icon="Plus"
              @click="append(data)"
              :disabled="node.level == 3"
              size="small"
              text
              bg
            >
              添加
            </el-button>
            <el-button
              type="danger"
              icon="Delete"
              :disabled="node.childNodes != 0"
              @click="remove(node, data)"
              size="small"
              text
              bg
            >
              删除
            </el-button>
          </span>
        </span>
      </template>
    </el-tree>
  </el-card>

  <el-dialog v-model="dialogFormVisible" title="添加分类">
    <el-form :model="catalogForm">
      <el-form-item label="分类名称">
        <el-input v-model="catalogForm.title" />
      </el-form-item>
    </el-form>
    <template #footer>
      <span class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取消</el-button>
        <el-button type="primary" @click="handleConfirm">确认</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>
import {
  reqTree,
  reqBatchDelete,
  reqUpdateDrop,
  reqDelete,
  reqAdd,
} from '@/api/catalog'
import { onMounted, ref, watch } from 'vue'
import { ElMessageBox, ElMessage } from 'element-plus'
const treeRef = ref()
let draggable = ref(true)
let dialogFormVisible = ref(false)
let catalogForm = ref({})
//append remove
const append = (data) => {
  //清空
  catalogForm.value = {}
  //赋值当前节前节点
  catalogForm.value.currentNode = data
  dialogFormVisible.value = true
  expandedKeyPid.value.push(data.cid)
}
const handleConfirm = async () => {
  let data = {
    title: catalogForm.value.title,
    pid: catalogForm.value.currentNode.cid,
  }
  await reqAdd(data)
  ElMessage.success('添加成功')
  dialogFormVisible.value = false
  expandedKey.value = expandedKeyPid.value
  await getTree()
}
const remove = (node, data) => {
  ElMessageBox.confirm(`是否批量删除【${data.title}】菜单?`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      expandedKeyPid.value.push(node.parent.data.cid)
      await reqDelete(data.cid)
      ElMessage.success('删除成功')
      expandedKey.value = expandedKeyPid.value
      await getTree()
    })
    .catch(() => {})
}
//搜索
const filterText = ref('')
watch(filterText, (val) => {
  treeRef.value.filter(val)
})
//过滤
const filterNode = (value, data) => {
  if (!value) return true
  return data.title.includes(value)
}

const defaultProps = {
  children: 'children',
  label: 'title',
}

const data = ref([])

const getTree = async () => {
  let result = await reqTree()
  data.value = result.data
  // console.log(result.data)
}
let expandedKeyPid = ref([])
let expandedKey = ref([])
//保存
const batchSave = async () => {
  await reqUpdateDrop(updateNodes.value)
  ElMessage.success('分类顺序等修改成功')
  maxLevel = 0
  updateNodes.value = []
  expandedKey = expandedKeyPid.value
  await getTree()
}

//删除
const batchDelete = async () => {
  ElMessageBox.confirm(`是否批量删除【${tids.value}】菜单?`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      await reqBatchDelete(tids.value)
      ElMessage.success('批量删除成功')
      tids.value = []
      expandedKey = expandedKeyPid.value
      await getTree()
    })
    .catch(() => {})
}

onMounted(() => {
  getTree()
})
let updateNodes = ref([])
/* 拖拽API */
/* 待删除id数组 */
let tids = ref([])
const handleCheck = (checkedNodes, treeStatus) => {
  tids.value = treeStatus.checkedKeys
  expandedKeyPid.value.push(...treeStatus.halfCheckedKeys)
}
/* 拖拽成功完成时触发的事件 */
const handleDrop = (draggingNode, dropNode, dropType, ev) => {
  // console.log('tree drop:', dropNode.label, dropType)
  //1、当前节点最新的父节点id
  let pid = 0
  let siblings = null
  if (dropType == 'before' || dropType == 'after') {
    pid = dropNode.parent.data.cid == undefined ? 0 : dropNode.parent.data.cid
    siblings = dropNode.parent.childNodes
  } else {
    pid = dropNode.data.cid
    siblings = dropNode.childNodes
  }
  expandedKeyPid.value.push(pid)
  //2、当前拖拽节点的最新顺序，
  for (let i = 0; i < siblings.length; i++) {
    if (siblings[i].data.cid == draggingNode.data.cid) {
      //如果遍历的是当前正在拖拽的节点
      updateNodes.value.push({
        cid: siblings[i].data.cid,
        sort: i,
        pid: pid,
      })
    } else {
      updateNodes.value.push({ cid: siblings[i].data.cid, sort: i })
    }
  }
}
//最深层级
let maxLevel = 0
let minLevel = 0
/* 拖拽时判定目标节点能否成为拖动目标位置 */
const allowDrop = (draggingNode, dropNode, type) => {
  maxLevel = draggingNode.level
  minLevel = draggingNode.level
  //当前节点不能大于3
  countNodeLevel(draggingNode)
  //1）、被拖动的当前节点总层数
  let deep = Math.abs(maxLevel - minLevel) + 1
  return type == 'inner'
    ? deep + dropNode.level <= 3
    : deep + dropNode.parent.level <= 3
}

//查询所有子节点
const countNodeLevel = (node) => {
  if (node.childNodes != null && node.childNodes.length > 0) {
    for (let i = 0; i < node.childNodes.length; i++) {
      maxLevel =
        node.childNodes[i].level > minLevel
          ? node.childNodes[i].level
          : minLevel
      countNodeLevel(node.childNodes[i])
    }
  }
}
</script>

<style lang="scss" scoped>
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>
